library(tidyverse)
library(lubridate)
library(plotly)
library(ggrepel)
df <- read_csv("covid_19_clean_complete.csv")
Parsed with column specification:
cols(
`Province/State` = col_character(),
`Country/Region` = col_character(),
Lat = col_double(),
Long = col_double(),
Date = col_character(),
Confirmed = col_double(),
Deaths = col_double(),
Recovered = col_double()
)
pop <- read.csv("API_SP.POP.TOTL_DS2_en_csv_v2_936048.csv")
pop <- tibble(country = pop$Country.Name, pop = pop$X2018)
tests <- read_csv("full-list-covid-19-tests-per-day.csv") %>%
mutate(tests = `Daily change in cumulative total tests`)
Parsed with column specification:
cols(
Entity = col_character(),
Code = col_character(),
Date = col_character(),
`Daily change in cumulative total tests` = col_double()
)
options(scipen=999)
covid <- df %>%
mutate(Date = mdy(Date)) %>%
group_by(`Country/Region`, Date) %>%
summarise(Confirmed = sum(Confirmed, na.rm = T),
Deaths = sum(Deaths, na.rm = T),
Recovered = sum(Recovered, na.rm = T)) %>%
arrange(`Country/Region`, Date)
final <- covid %>%
group_by(`Country/Region`) %>%
filter(Confirmed >= 100) %>%
mutate(hunfirst = if_else( Date == min(Date), 1, 0),
days_since_hun = row_number(),
marginal_confirmed = Confirmed - lag(Confirmed)) %>%
left_join( pop %>%
mutate(country = case_when(
country == "United States" ~ "US",
country == "Korea, Rep." ~ "South Korea",
TRUE ~ as.character(country))),
by = c("Country/Region" = "country")) %>%
drop_na() %>%
mutate(confirmed_permil = Confirmed/pop*1000000,
deaths_permil = Deaths/pop*1000000,
marginal_confirmed_permil = confirmed_permil - lag(confirmed_permil)) %>%
left_join(tests %>%
mutate(Date = mdy(Date),
Entity = if_else(Entity == "United States", "US", Entity)) %>%
select(Entity, Date, tests), by = c("Country/Region" = "Entity", "Date"))
final <- final %>%
left_join(final %>%
filter(confirmed_permil >= 20) %>%
group_by(`Country/Region`) %>%
mutate(days_sinc_twcon = row_number())) %>%
left_join(final %>%
filter(deaths_permil >= 3) %>%
group_by(`Country/Region`) %>%
mutate(days_sinc_threed = row_number()))
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
write_csv(final, "covid_final.csv")
graph_confirmed <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_since_hun, y = Confirmed, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
last <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
group_by(`Country/Region`) %>%
filter(days_since_hun == max(days_since_hun))
graph <- graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = Confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Confirmed cases by days since 100th case", x = "", y = "")
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
NA
graph_confirmed <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_since_hun, y = marginal_confirmed, color = `Country/Region`)) +
geom_smooth(se=F) + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Marginal confirmed cases by days since 100th case", x = "", y = "")
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 9 rows containing non-finite values (stat_smooth).
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
graph_confirmed <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_twcon, y = confirmed_permil, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_sinc_twcon + 2, y = confirmed_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Confirmed per 1M by days since 20th case per 1M", x = "", y = "")
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
NA
graph_confirmed <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_twcon, y = marginal_confirmed_permil, color = `Country/Region`)) +
geom_smooth(se=F) + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_sinc_twcon + 2, y = marginal_confirmed_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Marginal confirmed per 1M by days since 20th case per 1M", x = "", y = "")
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 123 rows containing non-finite values (stat_smooth).pseudoinverse used at 4neighborhood radius 2reciprocal condition number 0
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
NA
graph_confirmed <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60,
!is.na(tests)) %>%
ggplot(aes(x = days_since_hun, y = marginal_confirmed/tests, color = `Country/Region`)) +
geom_smooth(se = F) + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed/tests, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "% of tests confirmed by days since 100th confirmed", x = "", y = "")
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 3 rows containing non-finite values (stat_smooth).
plotly$height <- 900
plotly$width <- 1200
plotly$sizingPolicy$defaultWidth <- 1200
plotly$sizingPolicy$defaultHeight <- 900
plotly
graph_confirmed <- final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_threed, y = deaths_permil, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_sinc_threed + 2, y = deaths_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Deaths per 1M by days since 3rd death per 1M", x = "", y = "")
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQotLS0KdGl0bGU6ICJSIE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGdncmVwZWwpCmRmIDwtIHJlYWRfY3N2KCJjb3ZpZF8xOV9jbGVhbl9jb21wbGV0ZS5jc3YiKQpwb3AgPC0gcmVhZC5jc3YoIkFQSV9TUC5QT1AuVE9UTF9EUzJfZW5fY3N2X3YyXzkzNjA0OC5jc3YiKQpwb3AgPC0gdGliYmxlKGNvdW50cnkgPSBwb3AkQ291bnRyeS5OYW1lLCBwb3AgPSBwb3AkWDIwMTgpCnRlc3RzIDwtIHJlYWRfY3N2KCJmdWxsLWxpc3QtY292aWQtMTktdGVzdHMtcGVyLWRheS5jc3YiKSAlPiUKICBtdXRhdGUodGVzdHMgPSBgRGFpbHkgY2hhbmdlIGluIGN1bXVsYXRpdmUgdG90YWwgdGVzdHNgKQpvcHRpb25zKHNjaXBlbj05OTkpCmBgYAoKCmBgYHtyfQpjb3ZpZCA8LSBkZiAlPiUKICBtdXRhdGUoRGF0ZSA9IG1keShEYXRlKSkgJT4lCiAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCwgRGF0ZSkgJT4lCiAgc3VtbWFyaXNlKENvbmZpcm1lZCA9IHN1bShDb25maXJtZWQsIG5hLnJtID0gVCksCiAgICAgICAgICAgIERlYXRocyA9IHN1bShEZWF0aHMsIG5hLnJtID0gVCksCiAgICAgICAgICAgIFJlY292ZXJlZCA9IHN1bShSZWNvdmVyZWQsIG5hLnJtID0gVCkpICU+JQogIGFycmFuZ2UoYENvdW50cnkvUmVnaW9uYCwgRGF0ZSkKCgpmaW5hbCA8LSBjb3ZpZCAlPiUKICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUKICBmaWx0ZXIoQ29uZmlybWVkID49IDEwMCkgJT4lCiAgbXV0YXRlKGh1bmZpcnN0ID0gaWZfZWxzZSggRGF0ZSA9PSBtaW4oRGF0ZSksIDEsIDApLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA9IHJvd19udW1iZXIoKSwKICAgICAgICAgbWFyZ2luYWxfY29uZmlybWVkID0gQ29uZmlybWVkIC0gbGFnKENvbmZpcm1lZCkpICU+JQogIGxlZnRfam9pbiggcG9wICU+JQogICAgICAgICAgICAgICBtdXRhdGUoY291bnRyeSA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICBjb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIiB+ICJVUyIsCiAgICAgICAgICAgICAgICAgY291bnRyeSA9PSAiS29yZWEsIFJlcC4iIH4gIlNvdXRoIEtvcmVhIiwKICAgICAgICAgICAgICAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKGNvdW50cnkpKSksIAogICAgICAgICAgICAgYnkgPSBjKCJDb3VudHJ5L1JlZ2lvbiIgPSAiY291bnRyeSIpKSAlPiUKICBkcm9wX25hKCkgJT4lCiAgbXV0YXRlKGNvbmZpcm1lZF9wZXJtaWwgPSBDb25maXJtZWQvcG9wKjEwMDAwMDAsCiAgICAgICAgIGRlYXRoc19wZXJtaWwgPSBEZWF0aHMvcG9wKjEwMDAwMDAsCiAgICAgICAgIG1hcmdpbmFsX2NvbmZpcm1lZF9wZXJtaWwgPSBjb25maXJtZWRfcGVybWlsIC0gbGFnKGNvbmZpcm1lZF9wZXJtaWwpKSAlPiUKICBsZWZ0X2pvaW4odGVzdHMgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKERhdGUgPSBtZHkoRGF0ZSksCiAgICAgICAgICAgICAgICAgICAgIEVudGl0eSA9IGlmX2Vsc2UoRW50aXR5ID09ICJVbml0ZWQgU3RhdGVzIiwgIlVTIiwgRW50aXR5KSkgJT4lCiAgICAgICAgICAgICAgc2VsZWN0KEVudGl0eSwgRGF0ZSwgdGVzdHMpLCBieSA9IGMoIkNvdW50cnkvUmVnaW9uIiA9ICJFbnRpdHkiLCAiRGF0ZSIpKQoKCmZpbmFsIDwtIGZpbmFsICU+JQogIGxlZnRfam9pbihmaW5hbCAlPiUKICAgICAgICAgICAgICBmaWx0ZXIoY29uZmlybWVkX3Blcm1pbCA+PSAyMCkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKGRheXNfc2luY190d2NvbiA9IHJvd19udW1iZXIoKSkpICU+JQogIGxlZnRfam9pbihmaW5hbCAlPiUKICAgICAgICAgICAgICBmaWx0ZXIoZGVhdGhzX3Blcm1pbCA+PSAzKSAlPiUKICAgICAgICAgICAgICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUKICAgICAgICAgICAgICBtdXRhdGUoZGF5c19zaW5jX3RocmVlZCA9IHJvd19udW1iZXIoKSkpCgp3cml0ZV9jc3YoZmluYWwsICJjb3ZpZF9maW5hbC5jc3YiKQogIAoKYGBgCgoKCgoKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgYygiVVMiLCAiQ2hpbmEiLCAiSXRhbHkiLCAiU3BhaW4iLCAiR2VybWFueSIsICJGcmFuY2UiLCAiSXNyYWVsIiwgIlN3ZWRlbiIsICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJTb3V0aCBLb3JlYSIpLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNlX2h1biwgeSA9IENvbmZpcm1lZCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gKSkgKyAKICBnZW9tX2xpbmUoKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCmxhc3QgPC0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjKCJVUyIsICJDaGluYSIsICJJdGFseSIsICJTcGFpbiIsICJHZXJtYW55IiwgIkZyYW5jZSIsICJJc3JhZWwiLCAiU3dlZGVuIiwgIkphcGFuIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlNvdXRoIEtvcmVhIiksCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjApICU+JQogIGdyb3VwX2J5KGBDb3VudHJ5L1JlZ2lvbmApICU+JQogIGZpbHRlcihkYXlzX3NpbmNlX2h1biA9PSBtYXgoZGF5c19zaW5jZV9odW4pKQoKZ3JhcGggPC0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jZV9odW4gKyAyLCB5ID0gQ29uZmlybWVkLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIkNvbmZpcm1lZCBjYXNlcyBieSBkYXlzIHNpbmNlIDEwMHRoIGNhc2UiLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPC0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0IDwtIDkwMApwbG90bHkkd2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA8LSA5MDAKcGxvdGx5CiAKYGBgCgoKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgYygiVVMiLCAiQ2hpbmEiLCAiSXRhbHkiLCAiU3BhaW4iLCAiR2VybWFueSIsICJGcmFuY2UiLCAiSXNyYWVsIiwgIlN3ZWRlbiIsICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJTb3V0aCBLb3JlYSIpLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNlX2h1biwgeSA9IG1hcmdpbmFsX2NvbmZpcm1lZCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gKSkgKyAKICBnZW9tX3Ntb290aChzZT1GKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCgpncmFwaCA8LSBncmFwaF9jb25maXJtZWQgKyAKICBnZW9tX3RleHQoYWVzKHggPSBkYXlzX3NpbmNlX2h1biArIDIsIHkgPSBtYXJnaW5hbF9jb25maXJtZWQsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIk1hcmdpbmFsIGNvbmZpcm1lZCBjYXNlcyBieSBkYXlzIHNpbmNlIDEwMHRoIGNhc2UiLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPC0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0IDwtIDkwMApwbG90bHkkd2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA8LSA5MDAKcGxvdGx5CmBgYAoKCgoKCmBgYHtyfQpncmFwaF9jb25maXJtZWQgPC0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjKCJVUyIsICJDaGluYSIsICJJdGFseSIsICJTcGFpbiIsICJHZXJtYW55IiwgIkZyYW5jZSIsICJJc3JhZWwiLCAiU3dlZGVuIiwgIkphcGFuIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlNvdXRoIEtvcmVhIiksCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjApICU+JQogIGdncGxvdChhZXMoeCA9IGRheXNfc2luY190d2NvbiwgeSA9IGNvbmZpcm1lZF9wZXJtaWwsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCkpICsgCiAgZ2VvbV9saW5lKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgoKZ3JhcGggPC0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jX3R3Y29uICsgMiwgeSA9IGNvbmZpcm1lZF9wZXJtaWwsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIkNvbmZpcm1lZCBwZXIgMU0gIGJ5IGRheXMgc2luY2UgMjB0aCBjYXNlIHBlciAxTSIsIHggPSAiIiwgeSA9ICIiKQoKCiAgCiAgCnBsb3RseSA8LSBwbG90bHlfYnVpbGQoZ3JhcGgpCnBsb3RseSRoZWlnaHQgPC0gOTAwCnBsb3RseSR3aWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdFdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0SGVpZ2h0IDwtIDkwMApwbG90bHkKIApgYGAKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgYygiVVMiLCAiQ2hpbmEiLCAiSXRhbHkiLCAiU3BhaW4iLCAiR2VybWFueSIsICJGcmFuY2UiLCAiSXNyYWVsIiwgIlN3ZWRlbiIsICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJTb3V0aCBLb3JlYSIpLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNfdHdjb24sIHkgPSBtYXJnaW5hbF9jb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fc21vb3RoKHNlPUYpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgdGhlbWVfbWluaW1hbCgpIAogIAoKCmdyYXBoIDwtIGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY190d2NvbiArIDIsIHkgPSBtYXJnaW5hbF9jb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJNYXJnaW5hbCBjb25maXJtZWQgcGVyIDFNICBieSBkYXlzIHNpbmNlIDIwdGggY2FzZSBwZXIgMU0iLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPC0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0IDwtIDkwMApwbG90bHkkd2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA8LSA5MDAKcGxvdGx5CiAKYGBgCgoKCgoKCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA8LSBmaW5hbCAlPiUKICBmaWx0ZXIoYENvdW50cnkvUmVnaW9uYCAlaW4lIGMoIlVTIiwgIkNoaW5hIiwgIkl0YWx5IiwgIlNwYWluIiwgIkdlcm1hbnkiLCAiRnJhbmNlIiwgIklzcmFlbCIsICJTd2VkZW4iLCAiSmFwYW4iLCAiVW5pdGVkIEtpbmdkb20iLCAiU291dGggS29yZWEiKSwKICAgICAgICAgZGF5c19zaW5jZV9odW4gPCA2MCwKICAgICAgICAgIWlzLm5hKHRlc3RzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5c19zaW5jZV9odW4sIHkgPSBtYXJnaW5hbF9jb25maXJtZWQvdGVzdHMsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCkpICsgCiAgZ2VvbV9zbW9vdGgoc2UgPSBGKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCgpncmFwaCA8LSBncmFwaF9jb25maXJtZWQgKyAKICBnZW9tX3RleHQoYWVzKHggPSBkYXlzX3NpbmNlX2h1biArIDIsIHkgPSBtYXJnaW5hbF9jb25maXJtZWQvdGVzdHMsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIiUgb2YgdGVzdHMgY29uZmlybWVkIGJ5IGRheXMgc2luY2UgMTAwdGggY29uZmlybWVkIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDEyMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTIwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQpgYGAKCmBgYHtyfQpncmFwaF9jb25maXJtZWQgPC0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjKCJVUyIsICJDaGluYSIsICJJdGFseSIsICJTcGFpbiIsICJHZXJtYW55IiwgIkZyYW5jZSIsICJJc3JhZWwiLCAiU3dlZGVuIiwgIkphcGFuIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlNvdXRoIEtvcmVhIiksCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjApICU+JQogIGdncGxvdChhZXMoeCA9IGRheXNfc2luY190aHJlZWQsIHkgPSBkZWF0aHNfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fbGluZSgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgdGhlbWVfbWluaW1hbCgpIAogIAoKCmdyYXBoIDwtIGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY190aHJlZWQgKyAyLCB5ID0gZGVhdGhzX3Blcm1pbCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gLCBsYWJlbCA9IGBDb3VudHJ5L1JlZ2lvbmApLCBkYXRhID0gbGFzdCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIAogIGxhYnModGl0bGUgPSAiRGVhdGhzIHBlciAxTSBieSBkYXlzIHNpbmNlIDNyZCBkZWF0aCBwZXIgMU0iLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPC0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0IDwtIDkwMApwbG90bHkkd2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA8LSA5MDAKcGxvdGx5CmBgYAoKCgoKCgoKCgoKCgoKCgoKCg==